from abc import ABCMeta, abstractmethod

class IContext(object):
    pass

"""Data object"""
class Interruption(object):
    
    """Generates unique kinds"""
    KILL_PROCESS = "KILL_PROCESS Interruption"
    TIME_OUT     = "TIME_OUT Interruption"
    IO_REQUEST   = "IO_REQUEST Interruption"
    IO_FINISH    = "IO_FINISH Interruption"
    EXECUTE      = "EXECUTE Interruption"
    
    def __init__(self, __kind, __pcb, **kargs):
        self.kind = __kind
        self.pcb  = __pcb
        self.args = kargs

class InterruptionHandler(object):
    __metaclass__ = ABCMeta
    @abstractmethod
    def handle(self, pcb, kernel, args):
        pass
    
class KillHandler(InterruptionHandler):
    def handle(self, pcb, kernel, args):
        args["cpu"].set_free()
        kernel.delete_pcb(pcb)
   
class IORequestHandler(InterruptionHandler):
    def handle(self, pcb, kernel, args):
        kernel.send_to_io(pcb)

class IOFinishedHandler(InterruptionHandler):
    def handle(self, pcb, kernel, args):
        kernel.send_to_ready(pcb)
    
class TimeOutHandler(InterruptionHandler):
    def handle(self, pcb, kernel, args):
        kernel.output.send(pcb.process_name + " - Time out")
        args["cpu"].set_free()
        kernel.send_to_ready(pcb)
    
class ExecuteHandler(InterruptionHandler):
    def handle(self, pcb, kernel, args):
        kernel.load(args["program_name"], args["params"])
    
class InterruptionManager():
    
    def __init__(self, kernel, routines):
        self.__kernel = kernel
        self.__routines = routines
        
    def handle(self, interruption):
        handler = self.__routines[interruption.kind]
        handler.handle(interruption.pcb, self.__kernel, interruption.args)

